﻿using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;

namespace OpenCube.Nbt
{
	/// <summary>
	/// Dictionary holding Nbt data
	/// </summary>
	public interface INbtDictionary
		: IDictionary<string, object>
	{
	}

	public struct NbtElement
	{
		private sealed class NoValueObject  { }

		public static readonly NbtElement None = new NbtElement();
		public static readonly object NoValue = new NoValueObject();

		public static NbtElement Missing(string key)
		{
			return new NbtElement(key, NoValue);
		}

		public static NbtElement<TValue> Create<TValue>(string key, TValue value)
		{
			return new NbtElement<TValue>(key, value);
		}

		private readonly string _key;
		private readonly object _value;

		public NbtElement(string key, object value)
		{
			Contract.Requires<ArgumentNullException>(!string.IsNullOrEmpty(key));

			_key = key;
			_value = value;
		}

		/// <summary>
		/// Gets the key of the Nbt element
		/// </summary>
		public string Key { get { return _key; } }

		/// <summary>
		/// Gets the Value of the element
		/// </summary>
		public object Value { get { return _value; } }
	}

	public struct NbtElement<TValue>
	{
		private readonly string _key;
		private readonly TValue _value;

		public NbtElement(string key, TValue value)
		{
			Contract.Requires<ArgumentNullException>(!string.IsNullOrEmpty(key));

			_key = key;
			_value = value;
		}

		/// <summary>
		/// Gets the key of the Nbt element
		/// </summary>
		public string Key { get { return _key; } }

		/// <summary>
		/// Gets the Value of the element
		/// </summary>
		public TValue Value { get { return _value; } }

		public static implicit operator NbtElement(NbtElement<TValue> nbtElement)
		{
			return new NbtElement(nbtElement.Key, nbtElement.Value);
		}

		public static explicit operator NbtElement<TValue>(NbtElement nbtElement)
		{
			return new NbtElement<TValue>(nbtElement.Key, (TValue)nbtElement.Value);
		}
	}
}
